render: Make gtk_render_layout() use the snapshot API
authorBenjamin Otte <otte@redhat.com>
Sat, 14 Jul 2018 18:21:15 +0000 (20:21 +0200)
committerBenjamin Otte <otte@redhat.com>
Tue, 24 Jul 2018 18:55:45 +0000 (20:55 +0200)
This removes a lot of duplicated code.

gtk/gtkcssshadowsvalue.c
gtk/gtkcssshadowsvalueprivate.h
gtk/gtkcssshadowvalue.c
gtk/gtkcssshadowvalueprivate.h
gtk/gtkpango.c
gtk/gtkpango.h
gtk/gtkrender.c

index 729b87999101189b9833c6cac5cc2f2ef4e37d8f..6aa4c50a938b3627de4815e632799aff92f4f72f 100644 (file)
@@ -287,21 +287,6 @@ gtk_css_shadows_value_get_shadows (const GtkCssValue  *shadows,
     gtk_css_shadow_value_get_shadow (shadows->values[i], &out_shadows[i]);
 }
 
-void
-_gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows,
-                                     cairo_t           *cr,
-                                     PangoLayout       *layout)
-{
-  guint i;
-
-  g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
-
-  for (i = 0; i < shadows->len; i++)
-    {
-      _gtk_css_shadow_value_paint_layout (shadows->values[i], cr, layout);
-    }
-}
-
 void
 _gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows,
                                    cairo_t           *cr)
index 5bd78615f401fa297adbf2daf67d5893611f646c..30eb4eebd96fc122a6b75a554f339fc1d2f4762c 100644 (file)
@@ -41,10 +41,6 @@ gsize           gtk_css_shadows_value_get_n_shadows   (const GtkCssValue
 void            gtk_css_shadows_value_get_shadows    (const GtkCssValue        *shadows,
                                                       GskShadow                *out_shadows);
 
-void            _gtk_css_shadows_value_paint_layout   (const GtkCssValue        *shadows,
-                                                       cairo_t                  *cr,
-                                                       PangoLayout              *layout);
-
 void            _gtk_css_shadows_value_paint_icon     (const GtkCssValue        *shadows,
                                                       cairo_t                  *cr);
 
index 62e0db7340e59689b103dd51900afeeced329eb3..b57d6aa9f003879ba20d63c89c7ecc58ea863980 100644 (file)
@@ -430,143 +430,6 @@ gtk_css_shadow_value_finish_drawing (const GtkCssValue *shadow,
   return original_cr;
 }
 
-static const cairo_user_data_key_t radius_key;
-static const cairo_user_data_key_t layout_serial_key;
-
-GQuark pango_cached_blurred_surface_quark (void);
-
-G_DEFINE_QUARK (GtkCssShadowValue pango_cached_blurred_surface, pango_cached_blurred_surface)
-
-static cairo_surface_t *
-get_cached_pango_surface (PangoLayout       *layout,
-                          const GtkCssValue *shadow)
-{
-  cairo_surface_t *cached_surface = g_object_get_qdata (G_OBJECT (layout), pango_cached_blurred_surface_quark ());
-  guint cached_radius, cached_serial;
-  guint radius, serial;
-
-  if (!cached_surface)
-    return NULL;
-
-  radius = _gtk_css_number_value_get (shadow->radius, 0);
-  cached_radius = GPOINTER_TO_UINT (cairo_surface_get_user_data (cached_surface, &radius_key));
-  if (radius != cached_radius)
-    return NULL;
-
-  serial = pango_layout_get_serial (layout);
-  cached_serial = GPOINTER_TO_UINT (cairo_surface_get_user_data (cached_surface, &layout_serial_key));
-  if (serial != cached_serial)
-    return NULL;
-
-  return cached_surface;
-}
-
-static cairo_surface_t *
-make_blurred_pango_surface (cairo_t           *existing_cr,
-                            PangoLayout       *layout,
-                            const GtkCssValue *shadow)
-{
-  cairo_surface_t *surface;
-  cairo_t *cr;
-  gdouble radius, clip_radius;
-  gdouble x_scale, y_scale;
-  PangoRectangle ink_rect;
-
-  radius = _gtk_css_number_value_get (shadow->radius, 0);
-
-  pango_layout_get_pixel_extents (layout, &ink_rect, NULL);
-  clip_radius = gsk_cairo_blur_compute_pixels (radius);
-  x_scale = y_scale = 1;
-  cairo_surface_get_device_scale (cairo_get_target (existing_cr), &x_scale, &y_scale);
-
-  surface = cairo_surface_create_similar_image (cairo_get_target (existing_cr),
-                                                CAIRO_FORMAT_A8,
-                                                x_scale * (ink_rect.width + 2 * clip_radius),
-                                                y_scale * (ink_rect.height + 2 * clip_radius));
-  cairo_surface_set_device_scale (surface, x_scale, y_scale);
-  cairo_surface_set_device_offset (surface, -ink_rect.x + clip_radius, -ink_rect.y + clip_radius);
-  cr = cairo_create (surface);
-  cairo_move_to (cr, 0, 0);
-  _gtk_pango_fill_layout (cr, layout);
-  gsk_cairo_blur_surface (surface, radius * x_scale, GSK_BLUR_X | GSK_BLUR_Y);
-
-  cairo_destroy (cr);
-
-  return surface;
-}
-
-static cairo_surface_t *
-get_blurred_pango_surface (cairo_t           *cr,
-                           PangoLayout       *layout,
-                           const GtkCssValue *shadow)
-{
-  cairo_surface_t *surface;
-  guint radius, serial;
-
-  surface = get_cached_pango_surface (layout, shadow);
-  if (!surface)
-    {
-      surface = make_blurred_pango_surface (cr, layout, shadow);
-
-      /* Cache the surface on the PangoLayout */
-      radius = _gtk_css_number_value_get (shadow->radius, 0);
-      cairo_surface_set_user_data (surface, &radius_key, GUINT_TO_POINTER (radius), NULL);
-
-      serial = pango_layout_get_serial (layout);
-      cairo_surface_set_user_data (surface, &layout_serial_key, GUINT_TO_POINTER (serial), NULL);
-
-      g_object_set_qdata_full (G_OBJECT (layout), pango_cached_blurred_surface_quark (),
-                               surface, (GDestroyNotify) cairo_surface_destroy);
-    }
-
-  return surface;
-}
-
-void
-_gtk_css_shadow_value_paint_layout (const GtkCssValue *shadow,
-                                    cairo_t           *cr,
-                                    PangoLayout       *layout)
-{
-  g_return_if_fail (shadow->class == &GTK_CSS_VALUE_SHADOW);
-
-  /* We don't need to draw invisible shadows */
-  if (gdk_rgba_is_clear (_gtk_css_rgba_value_get_rgba (shadow->color)))
-    return;
-
-  if (!cairo_has_current_point (cr))
-    cairo_move_to (cr, 0, 0);
-
-  cairo_save (cr);
-
-  if (needs_blur (shadow))
-    {
-      cairo_surface_t *blurred_surface = get_blurred_pango_surface (cr, layout, shadow);
-      double x, y;
-      cairo_get_current_point (cr, &x, &y);
-      cairo_translate (cr, x, y);
-      cairo_translate (cr,
-                       _gtk_css_number_value_get (shadow->hoffset, 0),
-                       _gtk_css_number_value_get (shadow->voffset, 0));
-
-      gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color));
-      cairo_mask_surface (cr, blurred_surface, 0, 0);
-    }
-  else
-    {
-      /* The no blur case -- just paint directly. */
-      cairo_rel_move_to (cr,
-                         _gtk_css_number_value_get (shadow->hoffset, 0),
-                         _gtk_css_number_value_get (shadow->voffset, 0));
-      gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (shadow->color));
-      _gtk_pango_fill_layout (cr, layout);
-      cairo_rel_move_to (cr,
-                         - _gtk_css_number_value_get (shadow->hoffset, 0),
-                         - _gtk_css_number_value_get (shadow->voffset, 0));
-    }
-
-  cairo_restore (cr);
-}
-
 void
 _gtk_css_shadow_value_paint_icon (const GtkCssValue *shadow,
                                  cairo_t           *cr)
index e3113d106a8aff3ebe258dc148932bb0cc99c52a..b04beea9867ca8e325086e5fe3eed6a5dd456be2 100644 (file)
@@ -42,10 +42,6 @@ void            gtk_css_shadow_value_get_extents      (const GtkCssValue
 void            gtk_css_shadow_value_get_shadow       (const GtkCssValue        *value,
                                                        GskShadow                *shadow);
 
-void            _gtk_css_shadow_value_paint_layout    (const GtkCssValue        *shadow,
-                                                       cairo_t                  *cr,
-                                                       PangoLayout              *layout);
-
 void            _gtk_css_shadow_value_paint_icon      (const GtkCssValue        *shadow,
                                                       cairo_t                  *cr);
 void            _gtk_css_shadow_value_paint_box       (const GtkCssValue        *shadow,
index 2c87e8cb656935cea8132d2a30f4b6711689419b..1f6e70954ac48b40265dc72a7e6c666d4489e4cd 100644 (file)
 #include <pango/pangocairo.h>
 #include "gtkintl.h"
 
-#define GTK_TYPE_FILL_LAYOUT_RENDERER            (_gtk_fill_layout_renderer_get_type())
-#define GTK_FILL_LAYOUT_RENDERER(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRenderer))
-#define GTK_IS_FILL_LAYOUT_RENDERER(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_FILL_LAYOUT_RENDERER))
-#define GTK_FILL_LAYOUT_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRendererClass))
-#define GTK_IS_FILL_LAYOUT_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILL_LAYOUT_RENDERER))
-#define GTK_FILL_LAYOUT_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRendererClass))
-
-typedef struct _GtkFillLayoutRenderer      GtkFillLayoutRenderer;
-typedef struct _GtkFillLayoutRendererClass GtkFillLayoutRendererClass;
-
-struct _GtkFillLayoutRenderer
-{
-  PangoRenderer parent_instance;
-
-  cairo_t *cr;
-};
-
-struct _GtkFillLayoutRendererClass
-{
-  PangoRendererClass parent_class;
-};
-
-GType _gtk_fill_layout_renderer_get_type (void);
-
-G_DEFINE_TYPE (GtkFillLayoutRenderer, _gtk_fill_layout_renderer, PANGO_TYPE_RENDERER)
-
-static void
-gtk_fill_layout_renderer_draw_glyphs (PangoRenderer     *renderer,
-                                      PangoFont         *font,
-                                      PangoGlyphString  *glyphs,
-                                      int                x,
-                                      int                y)
-{
-  GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
-
-  cairo_move_to (text_renderer->cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
-  pango_cairo_show_glyph_string (text_renderer->cr, font, glyphs);
-}
-
-static void
-gtk_fill_layout_renderer_draw_glyph_item (PangoRenderer     *renderer,
-                                          const char        *text,
-                                          PangoGlyphItem    *glyph_item,
-                                          int                x,
-                                          int                y)
-{
-  GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
-
-  cairo_move_to (text_renderer->cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
-  pango_cairo_show_glyph_item (text_renderer->cr, text, glyph_item);
-}
-
-static void
-gtk_fill_layout_renderer_draw_rectangle (PangoRenderer     *renderer,
-                                         PangoRenderPart    part,
-                                         int                x,
-                                         int                y,
-                                         int                width,
-                                         int                height)
-{
-  GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
-
-  if (part == PANGO_RENDER_PART_BACKGROUND)
-    return;
-
-  cairo_rectangle (text_renderer->cr,
-                   (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
-                  (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
-  cairo_fill (text_renderer->cr);
-}
-
-static void
-gtk_fill_layout_renderer_draw_trapezoid (PangoRenderer     *renderer,
-                                         PangoRenderPart    part,
-                                         double             y1_,
-                                         double             x11,
-                                         double             x21,
-                                         double             y2,
-                                         double             x12,
-                                         double             x22)
-{
-  GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
-  cairo_matrix_t matrix;
-  cairo_t *cr;
-
-  cr = text_renderer->cr;
-
-  cairo_save (cr);
-
-  /* use identity scale, but keep translation */
-  cairo_get_matrix (cr, &matrix);
-  matrix.xx = matrix.yy = 1;
-  matrix.xy = matrix.yx = 0;
-  cairo_set_matrix (cr, &matrix);
-
-  cairo_move_to (cr, x11, y1_);
-  cairo_line_to (cr, x21, y1_);
-  cairo_line_to (cr, x22, y2);
-  cairo_line_to (cr, x12, y2);
-  cairo_close_path (cr);
-
-  cairo_fill (cr);
-
-  cairo_restore (cr);
-}
-
-static void
-gtk_fill_layout_renderer_draw_error_underline (PangoRenderer *renderer,
-                                               int            x,
-                                               int            y,
-                                               int            width,
-                                               int            height)
-{
-  GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
-
-  pango_cairo_show_error_underline (text_renderer->cr,
-                                    (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
-                                    (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
-}
-
-static void
-gtk_fill_layout_renderer_draw_shape (PangoRenderer   *renderer,
-                                     PangoAttrShape  *attr,
-                                     int              x,
-                                     int              y)
-{
-  GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
-  cairo_t *cr = text_renderer->cr;
-  PangoLayout *layout;
-  PangoCairoShapeRendererFunc shape_renderer;
-  gpointer                    shape_renderer_data;
-
-  layout = pango_renderer_get_layout (renderer);
-
-  if (!layout)
-       return;
-
-  shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout),
-                                                          &shape_renderer_data);
-
-  if (!shape_renderer)
-    return;
-
-  cairo_save (cr);
-
-  cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
-
-  shape_renderer (cr, attr, FALSE, shape_renderer_data);
-
-  cairo_restore (cr);
-}
-
-static void
-gtk_fill_layout_renderer_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (_gtk_fill_layout_renderer_parent_class)->finalize (object);
-}
-
-static void
-_gtk_fill_layout_renderer_init (GtkFillLayoutRenderer *renderer)
-{
-}
-
-static void
-_gtk_fill_layout_renderer_class_init (GtkFillLayoutRendererClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  
-  PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
-  
-  renderer_class->draw_glyphs = gtk_fill_layout_renderer_draw_glyphs;
-  renderer_class->draw_glyph_item = gtk_fill_layout_renderer_draw_glyph_item;
-  renderer_class->draw_rectangle = gtk_fill_layout_renderer_draw_rectangle;
-  renderer_class->draw_trapezoid = gtk_fill_layout_renderer_draw_trapezoid;
-  renderer_class->draw_error_underline = gtk_fill_layout_renderer_draw_error_underline;
-  renderer_class->draw_shape = gtk_fill_layout_renderer_draw_shape;
-
-  object_class->finalize = gtk_fill_layout_renderer_finalize;
-}
-
-void
-_gtk_pango_fill_layout (cairo_t     *cr,
-                        PangoLayout *layout)
-{
-  static GtkFillLayoutRenderer *renderer = NULL;
-  gboolean has_current_point;
-  double current_x, current_y;
-
-  has_current_point = cairo_has_current_point (cr);
-  cairo_get_current_point (cr, &current_x, &current_y);
-
-  if (renderer == NULL)
-    renderer = g_object_new (GTK_TYPE_FILL_LAYOUT_RENDERER, NULL);
-
-  cairo_save (cr);
-  cairo_translate (cr, current_x, current_y);
-
-  renderer->cr = cr;
-  pango_renderer_draw_layout (PANGO_RENDERER (renderer), layout, 0, 0);
-
-  cairo_restore (cr);
-
-  if (has_current_point)
-    cairo_move_to (cr, current_x, current_y);
-}
-
 static AtkAttributeSet *
 add_attribute (AtkAttributeSet  *attributes,
                AtkTextAttribute  attr,
index 216f928e8b6c356d6181407e69ce978b996eceb9..09c50b8731e6e0df4ae2931ea57570348bb007b0 100644 (file)
 
 G_BEGIN_DECLS
 
-void             _gtk_pango_fill_layout            (cairo_t         *cr,
-                                                    PangoLayout     *layout);
-
-
 AtkAttributeSet *_gtk_pango_get_default_attributes (AtkAttributeSet *attributes,
                                                     PangoLayout     *layout);
 
index 3c90bb03d2d5d0f13577660a3fdd270e2a1a3b69..ae772a7f918148838df566fc984c15e00320d062 100644 (file)
@@ -427,54 +427,6 @@ gtk_render_focus (GtkStyleContext *context,
                                 x, y, width, height);
 }
 
-static void
-prepare_context_for_layout (cairo_t *cr,
-                            gdouble x,
-                            gdouble y,
-                            PangoLayout *layout)
-{
-  const PangoMatrix *matrix;
-
-  matrix = pango_context_get_matrix (pango_layout_get_context (layout));
-
-  cairo_move_to (cr, x, y);
-
-  if (matrix)
-    {
-      cairo_matrix_t cairo_matrix;
-
-      cairo_matrix_init (&cairo_matrix,
-                         matrix->xx, matrix->yx,
-                         matrix->xy, matrix->yy,
-                         matrix->x0, matrix->y0);
-
-      cairo_transform (cr, &cairo_matrix);
-    }
-}
-
-static void
-gtk_do_render_layout (GtkStyleContext *context,
-                      cairo_t         *cr,
-                      gdouble          x,
-                      gdouble          y,
-                      PangoLayout     *layout)
-{
-  const GdkRGBA *fg_color;
-
-  cairo_save (cr);
-  fg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR));
-
-  prepare_context_for_layout (cr, x, y, layout);
-
-  _gtk_css_shadows_value_paint_layout (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_TEXT_SHADOW),
-                                       cr, layout);
-
-  gdk_cairo_set_source_rgba (cr, fg_color);
-  pango_cairo_show_layout (cr, layout);
-
-  cairo_restore (cr);
-}
-
 /**
  * gtk_render_layout:
  * @context: a #GtkStyleContext
@@ -492,11 +444,24 @@ gtk_render_layout (GtkStyleContext *context,
                    gdouble          y,
                    PangoLayout     *layout)
 {
+  GtkSnapshot *snapshot;
+  GskRenderNode *node;
+
   g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
   g_return_if_fail (PANGO_IS_LAYOUT (layout));
   g_return_if_fail (cr != NULL);
 
-  gtk_do_render_layout (context, cr, x, y, layout);
+  snapshot = gtk_snapshot_new ();
+  gtk_snapshot_render_layout (snapshot, context, x, y, layout); 
+  node = gtk_snapshot_free_to_node (snapshot);
+  if (node == NULL)
+    return;
+
+  cairo_save (cr);
+  gsk_render_node_draw (node, cr);
+  cairo_restore (cr);
+
+  gsk_render_node_unref (node);
 }
 
 static void